package com.zzyl.nursing.util;

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;

/**
 * 身份证工具类
 */
public class IDCardUtils {

    // 身份证号码正则表达式（支持15位和18位）
    private static final String ID_CARD_PATTERN = "(^\\d{15}$)|(^\\d{17}([0-9]|X|x)$)";
    
    // 日期格式化器
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

    /**
     * 从身份证号码计算年龄
     * @param idCardNo 身份证号码
     * @return 年龄（周岁）
     * @throws IllegalArgumentException 如果身份证号码无效
     */
    public static int getAgeFromIDCard(String idCardNo) {
//        if (!isValidIDCard(idCardNo)) {
//            throw new IllegalArgumentException("无效的身份证号码");
//        }

        LocalDate birthDate = getBirthDateFromIDCard(idCardNo);
        LocalDate currentDate = LocalDate.now();
        
        return Period.between(birthDate, currentDate).getYears();
    }

    /**
     * 从身份证号码获取出生日期
     * @param idCardNo 身份证号码
     * @return 出生日期
     */
    public static LocalDate getBirthDateFromIDCard(String idCardNo) {
        String birthDateStr;
        if (idCardNo.length() == 15) {
            // 15位身份证：7-12位是出生年月日，格式为YYMMDD
            birthDateStr = "19" + idCardNo.substring(6, 12);
        } else {
            // 18位身份证：7-14位是出生年月日，格式为YYYYMMDD
            birthDateStr = idCardNo.substring(6, 14);
        }
        
        return LocalDate.parse(birthDateStr, DATE_FORMATTER);
    }

    /**
     * 验证身份证号码是否有效
     * @param idCardNo 身份证号码
     * @return true如果有效，false无效
     */
    public static boolean isValidIDCard(String idCardNo) {
        if (idCardNo == null || idCardNo.trim().isEmpty()) {
            return false;
        }
        
        // 基础格式校验
        if (!Pattern.matches(ID_CARD_PATTERN, idCardNo)) {
            return false;
        }
        
        // 如果是18位身份证，校验校验位
        if (idCardNo.length() == 18) {
            return validateCheckDigit(idCardNo);
        }
        
        return true;
    }

    /**
     * 验证18位身份证的校验位
     * @param idCardNo 18位身份证号码
     * @return true如果校验位正确，false不正确
     */
    private static boolean validateCheckDigit(String idCardNo) {
        // 加权因子
        int[] weightFactors = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        // 校验码对应值
        char[] checkDigits = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
        
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (idCardNo.charAt(i) - '0') * weightFactors[i];
        }
        
        int mod = sum % 11;
        char checkDigit = checkDigits[mod];
        
        return Character.toUpperCase(idCardNo.charAt(17)) == checkDigit;
    }

    /**
     * 从身份证号码获取性别
     * @param idCardNo 身份证号码
     * @return 性别：1-男，0-女
     * @throws IllegalArgumentException 如果身份证号码无效
     */
    public static int getGenderFromIDCard(String idCardNo) {
        if (!isValidIDCard(idCardNo)) {
            throw new IllegalArgumentException("无效的身份证号码");
        }
        
        int genderDigit;
        if (idCardNo.length() == 15) {
            // 15位身份证：第15位是性别，奇数为男，偶数为女
            genderDigit = idCardNo.charAt(14) - '0';
        } else {
            // 18位身份证：第17位是性别，奇数为男，偶数为女
            genderDigit = idCardNo.charAt(16) - '0';
        }
        
        return genderDigit % 2 == 1 ? 1 : 0;
    }

    /**
     * 将15位身份证号码升级为18位
     * @param idCardNo15 15位身份证号码
     * @return 18位身份证号码
     * @throws IllegalArgumentException 如果身份证号码无效
     */
    public static String convert15To18(String idCardNo15) {
        if (idCardNo15 == null || idCardNo15.length() != 15 || !isValidIDCard(idCardNo15)) {
            throw new IllegalArgumentException("无效的15位身份证号码");
        }
        
        // 前6位地区码 + 19 + 出生年月日 + 顺序码
        StringBuilder idCardNo18 = new StringBuilder()
            .append(idCardNo15.substring(0, 6))
            .append("19")
            .append(idCardNo15.substring(6));
        
        // 计算校验位
        int[] weightFactors = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        char[] checkDigits = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
        
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (idCardNo18.charAt(i) - '0') * weightFactors[i];
        }
        
        int mod = sum % 11;
        idCardNo18.append(checkDigits[mod]);
        
        return idCardNo18.toString();
    }
}